#ifndef __ATMOS_MasterServer_h__
#define __ATMOS_MasterServer_h__

#include "ATMOS_Common.h"
#include "ATMOS_PacketListener.h"
#include "ATMOS_MasterServerDatabase.h"
#include "ATMOS_PacketID.h"

namespace ATMOS {

//! Maintains a list of game clients and servers, and facilitates their connection
/*! The MasterServer maintains a list of game servers and game clients.  Connected game clients can 
 * request a list of servers (with certain filters) and then request a connection to one of those
 * game servers.
 * 
 * Applications that wish to register as a game client or game server must use the MSClient class.
 * 
 * The MasterServer uses a postgres database to store connection information.  The database
 * management code is contained within the MasterServerDatabase class.
 */
class AtmosExport MasterServer : 
	public PacketListener, 
	public AutoHandler<MasterServer,Packet*,void,PacketID>
{
	typedef std::map<std::string,MSClientInfo*> ClientMap;
	typedef std::pair<MSClientInfo*,MSClientInfo*> ClientPair;
		
public:
	MasterServer( NetworkManager *networkManager, const DatabaseConnectionInfo &databaseInfo );
	~MasterServer();

	// PacketListener
	//----------------------------------------------------------------------------------------------
	virtual void onAtmosPacket( Packet *packet );		
	virtual void onDisconnectionNotification( const std::string &senderGUID );
	virtual void onAlreadyConnected( const std::string &senderGUID );
	virtual void onIncompatibleProtocolVersion( const std::string &senderGUID );
	virtual void onRemoteDisconnectionNotification( const std::string &senderGUID );
	virtual void onRemoteConnectionLost( const std::string &senderGUID );
	virtual void onNewIncomingConnection( const std::string &senderGUID );
	virtual void onConnectionBanned( const std::string &senderGUID );
	virtual void onConnectionAttemptFailed( const std::string &senderGUID );
	virtual void onNoFreeIncomingConnections( const std::string &senderGUID );
	virtual void onInvalidPassword( const std::string &senderGUID );
	virtual void onConnectionLost( const std::string &senderGUID );
	virtual void onConnectionRequestAccepted( const std::string &senderGUID );
	virtual void onUnknownPacket( const std::string &senderGUID );

	//! get the number of connected game servers
	int getNumWaitingServers();
	//! get teh number of connected game clients
	int getNumWaitingClients();

	//! get a subsection of the servers list
	GameServerInfoList getWaitingServers( int start, int length );
	//! get a subsection of the clients list
	GameClientInfoList getWaitingClients( int start, int length );

	//! check whether an MSClient with a given GUID is a server
	bool isServer( const std::string &guid );
	//! check whether an MSClient with a given GUID is a client
	bool isClient( const std::string &guid );

	//! get the server info for the MSClient with the given GUID (MSClient must represent server)
	GameServerInfo getServerInfo( const std::string &guid );
	//! get the client info for the MSClient with the given GUID (MSClient must represent client)
	GameClientInfo getClientInfo( const std::string &guid );

	//! remove all servers from registration
	void removeAllServers();
	//! remove all clients from registration
	void removeAllClients();

private:
	// master server packet handlers
	//----------------------------------------------------------------------------------------------
	void onMSRegisterClient( Packet *packet );
	void onMSUnregisterClient( Packet *packet );		
	void onMSConnectionRequest( Packet *packet );
	void onMSConnectionEstablished( Packet *packet );
	void onMSConnectionFailed( Packet *packet );
	void onMSRequestServerList( Packet *packet );

	//! send a message to both a client and target server that their connection has been approved
	void sendCLGameConnectionApproved( const std::string &clientGUID, 
		const std::string &serverGUID );
	//! send a message to both a clietn and target server that their connection has been denied
	void sendCLGameConnectionDenied( const std::string &clientGUID,
		const std::string &serverGUID );
	//! send a server list to the MSClient with the given GUID
	void sendCLReceiveServerList( int start, int length, const std::string &returnGUID );
		
protected:
	MasterServerDatabase mDatabase;
};

} // end namespace ATMOS

#endif